package demoMod.gdxform.abstracts;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import demoMod.gdxform.core.ActionManager;
import demoMod.gdxform.interfaces.Element;
import demoMod.gdxform.interfaces.KeyboardEventSubscriber;
import demoMod.gdxform.interfaces.MouseEventSubscriber;
import demoMod.gdxform.interfaces.ResizeEventSubscriber;

public abstract class ScrollBar implements Element, MouseEventSubscriber, KeyboardEventSubscriber, ResizeEventSubscriber {
    private Container<? extends Element> parent;
    private float x;
    private float y;
    private float width;
    private float height;
    private boolean enabled = true;
    private boolean visible = true;
    private String id = "";

    private float progress;
    private float barLength;

    private Color barColor = Color.GRAY.cpy();
    private Color background = Color.CLEAR.cpy();
    protected Texture bgTexture;
    protected Texture barTexture;
    private final ActionManager actionManager;

    protected boolean mouseDown = false;

    public ScrollBar(float x, float y, float width, float height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        actionManager = new ActionManager();
        setBarColor(barColor);
        setBackground(background);
    }

    @Override
    public String getId() {
        return this.id;
    }

    @Override
    public void setId(String id) {
        this.id = id;
    }

    @Override
    public void update() {
        actionManager.update();
    }

    @Override
    public abstract void render(SpriteBatch sb);

    public float getProgress() {
        return progress;
    }

    public void setProgress(float progress) {
        this.progress = progress;
        if (this.progress > 1.0F) {
            this.progress = 1.0F;
        }
        if (this.progress < 0.0F) {
            this.progress = 0.0F;
        }
    }

    public float getBarLength() {
        return barLength;
    }

    public void setBarLength(float barLength) {
        checkBarLength(barLength);
        this.barLength = barLength;
    }

    protected abstract void checkBarLength(float barLength);

    public Color getBarColor() {
        return barColor;
    }

    public void setBarColor(Color barColor) {
        refreshBarTexture(barColor);
        this.barColor = barColor;
    }

    private void refreshBarTexture(Color barColor) {
        Pixmap pixmap = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
        pixmap.setColor(barColor);
        pixmap.fill();
        if (this.barTexture != null) {
            this.barTexture.dispose();
        }
        this.barTexture = new Texture(pixmap);
    }

    @Override
    public Container<? extends Element> getParent() {
        return this.parent;
    }

    @Override
    public void setParent(Container<? extends Element> parent) {
        this.parent = parent;
    }

    @Override
    public float getX(boolean isAbsolute) {
        return isAbsolute && getParent() != null ? getParent().getX(true) + x : x;
    }

    @Override
    public float getY(boolean isAbsolute) {
        return isAbsolute && getParent() != null ? getParent().getY(true) + y : y;
    }

    @Override
    public void setX(float x) {
        this.x = x;
    }

    @Override
    public void setY(float y) {
        this.y = y;
    }

    @Override
    public float getWidth() {
        return this.width;
    }

    @Override
    public float getHeight() {
        return this.height;
    }

    @Override
    public void setWidth(float width) {
        this.width = width;
    }

    @Override
    public void setHeight(float height) {
        this.height = height;
    }

    @Override
    public Color getBackground() {
        return this.background;
    }

    @Override
    public void setBackground(Color background) {
        refreshBgTexture(background);
        this.background = background;
    }

    public void setBackground(Texture bgTexture) {
        if (this.bgTexture != null) {
            this.bgTexture.dispose();
        }
        this.bgTexture = bgTexture;
    }

    private void refreshBgTexture(Color background) {
        Pixmap pixmap = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
        pixmap.setColor(background);
        pixmap.fill();
        if (this.bgTexture != null) {
            this.bgTexture.dispose();
        }
        this.bgTexture = new Texture(pixmap);
    }

    @Override
    public boolean isResizable() {
        return false;
    }

    @Override
    public void setResizable(boolean resizable) {

    }

    @Override
    public boolean enabled() {
        return this.enabled;
    }

    @Override
    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    @Override
    public boolean visible() {
        return this.visible;
    }

    @Override
    public void setVisible(boolean visible) {
        this.visible = visible;
    }

    @Override
    public void dispose() {
        if (this.bgTexture != null) {
            this.bgTexture.dispose();
        }
        if (this.barTexture != null) {
            this.barTexture.dispose();
        }
    }

    @Override
    public boolean keyDown(int keyCode) {
        return false;
    }

    @Override
    public boolean keyUp(int keyCode) {
        return false;
    }

    @Override
    public boolean keyTyped(char key) {
        return false;
    }

    @Override
    public boolean clickDown(int screenX, int screenY, int button) {
        if (!(this.visible() || this.enabled())) return false;
        mouseDown = screenX >= getX(true) && screenX <= getX(true) + getWidth() &&
                Gdx.graphics.getHeight() - screenY >= getY(true) && Gdx.graphics.getHeight() - screenY <= getY(true) + getHeight() && button == Input.Buttons.LEFT;
        return mouseDown;
    }

    @Override
    public boolean clickUp(int screenX, int screenY, int button) {
        if (mouseDown) {
            mouseDown = false;
            return true;
        }
        return false;
    }

    @Override
    public boolean mouseMoved(int screenX, int screenY) {
        return false;
    }

    @Override
    public boolean scrolled(int amount) {
        if (!(this.visible() || this.enabled())) return false;
        this.setProgress(getProgress() + amount / 20.0F);
        return true;
    }

    @Override
    public boolean moveToElementBorder(Element element) {
        return false;
    }

    @Override
    public void resize(float deltaX, float deltaY, boolean fromParent) {

    }
}
